# -*- coding:utf-8 -*-

# @File     :api_v1
# @Author   :Yupeng
# @Date     :2018/10/29 16:43

from django.core.handlers.wsgi import WSGIRequest
from django.db.models import Count
from django.utils.translation import gettext as _

from hte.error.handle import abort_on_error
from hte.error.models import HTEError, HTEException
from hte.utils.general import require_methods_api, json_response
from .models import *
from apps.accounts.models import User
import datetime


def merge_list(x, y):
    return [a + b for a, b in zip(x, y)]


def get_class_root() -> MaterialCategory:
    '''
    获取全局根分类
    :return:
    '''
    c = MaterialCategory.objects.filter(level=0, parent=None).first()
    assert c is not None
    return c


def get_sub_classes(mat_class) -> list:
    '''
    获取该分类的子分类
    :param mat_class:
    :return:
    '''
    assert mat_class.leaf is False
    return MaterialCategory.objects.filter(parent_id=mat_class.id, level__gt=0)


def get_sub_leaf_class_list(mat_class: MaterialCategory) -> list:
    """
    获取指定分类的所有叶子分类
    :param mat_class: 父分类，不能是叶子节点
    :return: 所有叶子分类的列表
    """
    assert mat_class.leaf is False
    result = []
    for c in get_sub_classes(mat_class):
        result += [c] if c.leaf is True else get_sub_leaf_class_list(c)
    return result


def get_trend_sum_of_leaf_classes(classes, beg, end) -> list:
    """
    将一个叶子节点列表的trend按项目求和
    :param classes: 叶子节点的列表
    :param beg:
    :param end:
    :return:
    """
    result = None
    for c in classes:
        if result is None:
            result = ClassTrend.get_unique(c).get_trend_by_date(beg, end)
        else:
            # add
            li = ClassTrend.get_unique(c).get_trend_by_date(beg, end)
            result = [
                {'date': x['date'], 'data': merge_list(x['data'], y['data'])} for x, y in zip(result, li)
            ]
    return result


def get_class_trend(mat_class: MaterialCategory, beg: int, end: int) -> list:
    if mat_class.leaf:
        return ClassTrend.get_unique(mat_class).get_trend_by_date(beg, end)
    else:
        return get_trend_sum_of_leaf_classes(get_sub_leaf_class_list(mat_class), beg, end)


#
# def get_global_trend(beg: int, end: int) -> list:
#     pass


def get_class_count(mat_class: MaterialCategory) -> list:
    """
    获取某个分类的统计情况
    :param mat_class:
    :return:
    """
    if mat_class.leaf:
        return ClassCounter.get_unique(mat_class).to_list()
    else:
        classes = get_sub_leaf_class_list(mat_class)
        result = [0, 0, 0, 0]
        for c in classes:
            result = merge_list(result, ClassCounter.get_unique(c).to_list())
        return result


def query_materials_class(materials_class):
    assert materials_class is not None
    gl = get_class_count(materials_class)
    tr = get_class_trend(materials_class, get_6_month_before_now(), get_current_date())
    cc = None
    if materials_class.leaf is False:
        cc = [{'name': _(c.name), 'data': get_class_count(c)} for c in get_sub_classes(materials_class)]
    return json_response({'global': gl, 'trend': tr, 'class': cc})


@require_methods_api(['GET'])
def index(request):
    mc = get_class_root()
    return query_materials_class(mc)


@require_methods_api(['GET'])
def query_class(request: WSGIRequest, cid):
    mat_class = MaterialCategory.objects.filter(pk=cid).first()
    if mat_class is None:
        abort_on_error(HTEError.NOT_FOUND)
    return query_materials_class(mat_class)


@require_methods_api(['GET'])
def query_data(req: WSGIRequest, did: str):
    data = DataMeta.objects.filter(pk=did).first()
    if data is None:
        abort_on_error(HTEError.NOT_FOUND)
    else:
        return json_response(DataCounter.get_unique(data).to_list())


# @require_methods_api(['GET'])
# def trend(request):
#     try:
#         beg = int(request.GET['beg'])
#         end = int(request.GET['end'])
#
#         if check_date(beg, end) is False:
#             abort_on_error(HTEError.BAD_PARAMETER)
#
#         return json_response(get_global_trend(beg, end))
#     except KeyError:
#         abort_on_error(HTEError.FIELD_MISSING)
#     except ValueError:
#         abort_on_error(HTEError.WRONG_FIELD_TYPE)


@require_methods_api(['GET'])
def trend_of_class(request, cid):
    mat_class = MaterialCategory.objects.filter(pk=cid).first()

    if mat_class is None:
        abort_on_error(HTEError.NOT_FOUND)

    try:
        beg = int(request.GET['beg'])
        end = int(request.GET['end'])

        if check_date(beg, end) is False:
            abort_on_error(HTEError.BAD_PARAMETER)

        return json_response(get_class_trend(mat_class, beg, end))
    except KeyError:
        abort_on_error(HTEError.FIELD_MISSING)
    except ValueError:
        abort_on_error(HTEError.WRONG_FIELD_TYPE)


# 下面这几个API分别按时间、领域、作者来统计数据条数
@require_methods_api(['GET'])
def get_data_num(request):
    '''
    这个函数用于搜索页面初始化使用，即不输入任何查询关键词的时候，默认显示全局的数据统计
    返回按年份统计的数据条数(只返回最近五年)、按作者统计的数据条数并且给出排名
    :param request: 请求本身
    :return:
    '''
    this_year = datetime.datetime.now().year
    # year_num[]分别代表今年和过去四年的数据量
    year_num = [0, 0, 0, 0, 0]
    year_num[0] = len(DataMeta.objects.filter(add_time__year__gte=this_year))
    year_num[1] = len(DataMeta.objects.filter(add_time__year__gte=this_year - 1))
    year_num[2] = len(DataMeta.objects.filter(add_time__year__gte=this_year - 2))
    year_num[3] = len(DataMeta.objects.filter(add_time__year__gte=this_year - 3))
    year_num[4] = len(DataMeta.objects.filter(add_time__year__gte=this_year - 4))
    print(year_num)
    # author_num{}分别代表数据量前五名用户的用户名及数据量
    # author_num = dict()
    # author_num['r'] = 'fdsfa'
    domain_num = tuple(DataMeta.objects.all().values('category_id').annotate(count=Count('category_id')).order_by('-count'))
    author_num = tuple(DataMeta.objects.all().values('author_id').annotate(count=Count('author_id')).order_by('-count'))
    all_data_num = len(DataMeta.objects.all())
    return json_response(
        {'all_data_num': all_data_num, 'year_num': year_num, 'domain_num': domain_num, 'author_num': author_num}
    )
